﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace PDX.Toolkit
{
    /// <summary>
    /// Interaction logic for EnumControl.xaml
    /// </summary>
    public partial class EnumControl : UserControl
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="EnumControl"/> class.
        /// </summary>
        public EnumControl()
        {
            InitializeComponent();
        }
    }

    /// <summary>
    /// Converts a <see cref="IPropertyModel"/> to a collection of
    /// <see cref="EnumModel"/>s
    /// </summary>
    public class PropertyModelToEnumModelsConverter : IValueConverter
    {
        /// <summary>
        /// Converts a value.
        /// </summary>
        /// <param name="value">The value produced by the binding source.</param>
        /// <param name="targetType">The type of the binding target property.</param>
        /// <param name="parameter">The converter parameter to use.</param>
        /// <param name="culture">The culture to use in the converter.</param>
        /// <returns>
        /// A converted value. If the method returns null, the valid null value is used.
        /// </returns>
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var pm = value as IPropertyModel;

            var enumModels = new List<EnumModel>();

            if (pm == null)
            {
                return enumModels;
            }

            var enumType = pm.PropertyType;

            var _enums = Enum.GetValues(enumType);

            foreach (var _enum in _enums)
            {
                var model = new EnumModel(pm);

                model.Value = _enum;

                var fieldInfo = enumType.GetField(_enum.ToString());
                var desc = fieldInfo.GetSingleAttribute<DescriptionAttribute>();
                if (desc != null)
                {
                    model.Name = desc.Description;
                }
                else
                {
                    var name = Enum.GetName(pm.PropertyType, _enum);
                    model.Name = name;
                }

                enumModels.Add(model);
            }

            return enumModels;
        }

        /// <summary>
        /// Converts a value.
        /// </summary>
        /// <param name="value">The value that is produced by the binding target.</param>
        /// <param name="targetType">The type to convert to.</param>
        /// <param name="parameter">The converter parameter to use.</param>
        /// <param name="culture">The culture to use in the converter.</param>
        /// <returns>
        /// A converted value. If the method returns null, the valid null value is used.
        /// </returns>
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    /// <summary>
    /// A bindable model for a possible value of an enum type.
    /// </summary>
    public class EnumModel : INPC
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="EnumModel"/> class.
        /// </summary>
        /// <param name="pm">The pm.</param>
        public EnumModel(IPropertyModel pm)
        {
            PropModel = pm;
            PropModel.PropertyChanged += new PropertyChangedEventHandler(PropModel_PropertyChanged);
        }

        void PropModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            OnPropertyChanged("IsChecked");
        }

        /// <summary>
        /// Gets or sets the display name.
        /// </summary>
        /// <value>
        /// The name.
        /// </value>
        public string Name { get; set; }

        /// <summary>
        /// Gets or sets the value.
        /// </summary>
        /// <value>
        /// The value.
        /// </value>
        public object Value { get; set; }

        /// <summary>
        /// Gets or sets the prop model.
        /// </summary>
        /// <value>
        /// The prop model.
        /// </value>
        public IPropertyModel PropModel { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is checked.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is checked; otherwise, <c>false</c>.
        /// </value>
        public bool IsChecked
        {
            get
            {
                return PropModel.Value.Equals(Value);
            }
            set
            {
                if (value)
                {
                    PropModel.Value = Value;
                }
            }
        }
    }
}
